package com.fusion.misc.tests;

import static com.fusion.core.CoreSubsystem.BLOCK_SIZE;

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

import junit.framework.TestCase;

import com.fusion.core.CoreSubsystem;
import com.fusion.core.ResourceSingelton;
import com.fusion.core.T;
import com.fusion.core.file.blockstorage.BlockFile;
import com.fusion.core.file.blockstorage.BlockStorage;
import com.fusion.core.file.blockstorage.CacheStorage;
import com.fusion.core.file.filedatabase.FileDescriptor;
import com.fusion.core.file.filedatabase.FileType;

/**
 * @author SwethaShivakumar 
 * Project: fusion
 * Date: Mar 18, 2009
 * URL: http://fusionwiki.co.cc
 * Mail Me At: shiva@fusionproject.co.cc
 */
public class AbstractTestBlockStorage extends TestCase {
    private CoreSubsystem core;

    protected void setUp() throws Exception {
        super.setUp();
//        new TraceWindow();
        core = new CoreSubsystem();
        core.init(ResourceSingelton.getRl(), "testsuite/settings/maciek.xml");
    }

    public void testMain() throws Exception {
        BlockStorage bs = new CacheStorage("test/cache/_incomplete_", "test/cache", core);

        FileDescriptor fda[] = core.getFileManager().search("mp3", 5, FileType.EVERYTHING);

        System.out.println(" ****** Moving 5 files through block storage ...");

        for(int f=0;f<5 & f<fda.length;f++) {
            FileDescriptor fd = fda[f];
            fake(bs, fd, false);
        }

        System.out.println(" ****** Moving 1 half file ...");
        fake(bs, fda[6], true);

        System.out.println(" ****** Trying to move other halv ...");
        bs.shutdown();
        bs = new CacheStorage("test/cache/_incomplete_", "test/cache", core);
        fake(bs, fda[6], false);

        System.out.println("press any key to continure");
    }

    private void fake(BlockStorage bs, FileDescriptor fd, boolean breakInMiddle) throws IOException {
        System.out.println("Faking a download of "+fd+"...");

        FileInputStream in = new FileInputStream(fd.getFullPath());
        System.out.println("size: "+fd.getSize());

        int nBlocks = (int)(fd.getSize()/BLOCK_SIZE);
        if (fd.getSize() % BLOCK_SIZE != 0) nBlocks++;

        for(int i=0;i<nBlocks;i++) {
            byte buf[] = new byte[323333];
            int off = 0;
            System.out.println("block: "+i);
            for(;;) {
                int read = BLOCK_SIZE-off;
                if (read <= 0) break;
                if (read > buf.length) read = buf.length;
                read = in.read(buf, 0, read);
                if (read == -1) {
                    System.out.println("Got -1 in read. Should be done now.");
                    break;
                }
                if (read == 0) continue;

                //convert array to bytebyffer - this is temporary - nio will be used all over later
                ByteBuffer bbuf = ByteBuffer.allocate(read);
                bbuf.put(buf, 0, read);
                bbuf.flip();

                if (!bs.containsBlock(fd.getRootHash(), i)) {
                    int r = bs.saveSlice(fd.getRootHash(), i, off, bbuf, fd);
                    if(T.t)T.ass(r == read, "Mismatch");
                    if (off+r >= BlockFile.getBlockSize(i, fd.getSize())) {
                        if(T.t)T.ass(off+r <= BlockFile.getBlockSize(i, fd.getSize()), "Wrote outside!");
                        break;
                    }
                } else {
                    System.out.println("Skipping because block already exists.");
                }
                off += read;
                if (breakInMiddle && (i>nBlocks/2 || i>2)) return;
            }
        }
        System.out.println("all blocks should be done");
    }
}
